package com.supersoul.myself.service.impl;

import com.supersoul.myself.cache.TokenCache;
import com.supersoul.myself.dao.BlogCollectionDao;
import com.supersoul.myself.dao.BlogDao;
import com.supersoul.myself.dao.UserDao;
import com.supersoul.myself.entity.Blog;
import com.supersoul.myself.entity.BlogCollection;
import com.supersoul.myself.entity.User;
import com.supersoul.myself.enums.BlogEnum;
import com.supersoul.myself.enums.ScoreEnum;
import com.supersoul.myself.enums.ServiceEnum;
import com.supersoul.myself.ex.ServiceException;
import com.supersoul.myself.service.BlogService;
import com.supersoul.myself.util.PageVO;
import com.supersoul.myself.util.R;
import com.supersoul.myself.util.UUIDUtils;
import com.supersoul.myself.util.UpdateTool;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.jws.soap.SOAPBinding;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


@Service
@Slf4j
public class BlogServiceImpl implements BlogService {

    @Autowired
    private BlogDao blogDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private BlogCollectionDao blogCollectionDao;

    @Override
    public String saveBlog(Blog blog, User user) throws ServiceException {
        if (null == blog.getId()) {
            // create
            blog.buildCreate();
            blog.setCreatorId(user.getId());
            blog.setCreatorName(user.getUserName());
            user.setScore(user.getScore() + ScoreEnum.PUBLISH_BLOG.getScore());
            userDao.save(user);
        } else {
            // edit  这种做法编程简单了, 但性能受损
            blog.setUpdateTime(new Date());
            blog.setUpdatorId(user.getId());
            blog.setUpdatorName(user.getUserName());
            Blog blogSource = getBlogById(blog.getId());
            UpdateTool.copyNullProperties(blogSource, blog);
        }
        blogDao.save(blog);
        return blog.getId();
    }

    @Override
    public Blog findBlogById(String id)  throws ServiceException {
        Blog blog = blogDao.findById(id).orElse(null);
        // 阅读量处理
        blog.setViews(blog.getViews() + 1);
        User user = new User();
        user.setId(blog.getCreatorId());
        user.setUserName(blog.getCreatorName());
        UpdateTool.copyNullProperties(blog, blog);
        blogDao.save(blog);
        return blog;
    }

    private Blog getBlogById(String id)  throws ServiceException {
       return blogDao.findById(id).orElse(null);
    }

    @Override
    public void delBlogById(String id, User user) throws ServiceException {
        Blog blog = findBlogById(id);
        if (blog == null) {
            // 博客不存在
            return;
        }
        if (blog.getCreatorId().equals(user.getId())) {
            blogDao.delete(blog);
        }
    }

    @Override
    public Page<Blog> findBlogPerson(PageVO pageVO, Integer permissionState, Integer publishState, String cgId, Integer orderId, User user) throws ServiceException {
        List<Sort.Order> orderList = new ArrayList<>();
        if (orderId == null) {
            orderList.add(new Sort.Order(Sort.Direction.DESC, "createTime"));
        } else if (orderId == 1){
            orderList.add(new Sort.Order(Sort.Direction.ASC, "contentOrder"));
        } else if (orderId == 2){
            orderList.add(new Sort.Order(Sort.Direction.DESC, "contentOrder"));
        } else {
           orderList.add(new Sort.Order(Sort.Direction.DESC, "createTime"));
        }
        Pageable pageable = PageRequest.of(pageVO.getPageNum(), pageVO.getPageSize(), Sort.by(orderList));
        Specification<Blog> specification = new Specification<Blog>() {
            @Override
            public Predicate toPredicate(Root<Blog> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<Predicate>();
                if (permissionState != null){
                    predicates.add(criteriaBuilder.equal(root.get("permissionState"),permissionState));
                }
                if (publishState != null){
                    predicates.add(criteriaBuilder.equal(root.get("publishState"),publishState));
                }
                if (StringUtils.isNotEmpty(cgId)){
                    predicates.add(criteriaBuilder.equal(root.get("cgId"),cgId));
                }
                if (StringUtils.isNotEmpty(user.getId())) {
                    predicates.add(criteriaBuilder.equal(root.get("creatorId"),user.getId()));
                }
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
        return blogDao.findAll(specification, pageable);
    }

    @Override
    public Page<Blog> findBlogPublic(PageVO pageVO, String cgId) throws ServiceException {
        List<Sort.Order> orderList = new ArrayList<>();
        orderList.add(new Sort.Order(Sort.Direction.DESC, "createTime"));
        Pageable pageable = PageRequest.of(pageVO.getPageNum(), pageVO.getPageSize(), Sort.by(orderList));
        if (cgId == null) {
            // 无分类, 查全部
            return blogDao.findByPermissionStateAndPublishState(BlogEnum.PUBLIC_BLOG.getCode(),BlogEnum.ALREADY_PUBLISH.getCode(),pageable);
        } else {
            // 根据分类id查
            return blogDao.findByPermissionStateAndPublishStateAndCgId(BlogEnum.PUBLIC_BLOG.getCode(),BlogEnum.ALREADY_PUBLISH.getCode(), cgId, pageable);
        }
    }

    @Override
    public Integer clickLikes(String blogId) throws ServiceException {
        Blog blog = getBlogById(blogId);
        blog.setLikes(blog.getLikes() + 1);
        User user = new User();
        user.setId(blog.getCreatorId());
        user.setUserName(blog.getCreatorName());
        saveBlog(blog, user);
        return blog.getLikes();
    }

    @Override
    public Integer cancelLikes(String blogId) throws ServiceException {
        Blog blog = getBlogById(blogId);
        blog.setLikes(blog.getLikes() - 1);
        User user = new User();
        user.setId(blog.getCreatorId());
        user.setUserName(blog.getCreatorName());
        saveBlog(blog, user);
        return blog.getLikes();
    }


    @Override
    public R collectBlog(BlogCollection blogCollection) throws ServiceException {
        if (blogCollection.getId() == null) {
            // 收藏
            BlogCollection byBlogIdAndCreatorId = blogCollectionDao.findByBlogIdAndCreatorId(blogCollection.getBlogId(), blogCollection.getCreatorId());
            if (byBlogIdAndCreatorId != null) {
                return R.failed(ServiceEnum.ALREADY_COLLECT_ERROR);
            }
            blogCollection.buildCreate();
            blogCollectionDao.save(blogCollection);
        } else {
            // 取消收藏
            Blog blog = getBlogById(blogCollection.getBlogId());
            if (blog == null) {
                // 博客不存在
                return R.failed(ServiceEnum.BLOG_NOTEXISTS_ERROR);
            }
            blogCollectionDao.delete(blogCollection);
        }
        return R.success();
    }

    @Override
    public Page<BlogCollection> getUserBlogCollectionPage(User user, PageVO pageVO) {
        List<Sort.Order> orderList = new ArrayList<>();
        orderList.add(new Sort.Order(Sort.Direction.DESC, "createTime"));
        Pageable pageable = PageRequest.of(pageVO.getPageNum(), pageVO.getPageSize(), Sort.by(orderList));
        Page<BlogCollection> blogCollectionPage = blogCollectionDao.findByCreatorId(user.getId(), pageable);
        return blogCollectionPage;
    }


}
